package ru.emms.codemeter.ui.forms;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;
import com.intellij.uiDesigner.core.Spacer;
import ru.emms.codemeter.exportdata.Exporter;
import ru.emms.codemeter.metrics.MetricsManager;
import ru.emms.codemeter.metrics.calculators.*;
import ru.emms.codemeter.tables.ColumnGroup;
import ru.emms.codemeter.tables.GroupableTableHeader;
import ru.emms.codemeter.ui.BaloonNotificationDatabaseListener;
import ru.emms.codemeter.ui.CalculateMetricsProgressTask;

import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.List;

/**
 * User: nastya.kuz
 * Date: 28.07.2010
 * <p/>
 * Главное окно плагина
 */
public class ResultViewForm
        extends JFrame {

    private static final Color DATABASE_SUCCESS_COLOR = Color.BLACK;
    private JPanel rootPanel;
    private JTabbedPane resultViewTabbedPane1;
    private JButton applyButton;
    private JButton addModuleButton;
    private JComboBox moduleTableComboBox;
    private JComboBox firstRevisionComboBox;
    private JComboBox lastRevisionComboBox;
    private JCheckBox classCheckBox;
    private JCheckBox abstractClassCheckBox;
    private JCheckBox interfaceCheckBox;
    private JCheckBox codeLineCheckBox;
    private JCheckBox codeLineRealCheckBox;
    // Компоненты с индексом 1 относятся к панели, на которой будет отображаться график зависимости значения
    // выбранной метрики от ревизии для одного или нескольких модулей
    private JComboBox metricsGraphicComboBox1;
    private JButton unloadGraphicButton1;
    //Компоненты с индексом 2 относятся к панели, на которой будет отображаться график зависимости значения
    //нескольких метрик от ревизии для выбранного модуля
    private JTable revisionTable;
    private JButton exportTablButton;
    private JPanel metricGraphic1;
    private JComboBox metricsGraphicComboBox2;
    private JComboBox moduleGraphicComboBox2;
    private JButton unloadGraphicButton2;
    private JButton buildGraphic1;
    private JButton buildGraphic2;
    private JPanel metricGraphic2;
    private JLabel bottomLabel;
    private JFrame addModuleForm;
    private PieChartGraphic pieChart;
    private BarChartGraphic chartBar;
    private List<Module> allModules;
    private List<Module> selectedModules;
    private List<MetricCalculator> metricCalculators;
    private Map<String, Map<Long, List<Long>>> metricsValues = new HashMap<String, Map<Long, List<Long>>>();
    private List<Long> versions;
    private List<Long> allVersions;
    private List<Module> resultModules;
    private MetricsManager metricsManager;
    private FileNameExtensionFilter graphicFileFilter = new FileNameExtensionFilter("png files", "png");
    private FileNameExtensionFilter tableFileFilter = new FileNameExtensionFilter("csv files", "csv");
    private Logger log = Logger.getInstance(getClass().getName());

    public JPanel getRootPanel() {
        return rootPanel;
    }

    /**
     * Конструктор формы, инициализирует компоненты, описывает действия при нажатии на кнопки
     *
     * @param s
     * @param metricsManager объект MetricsManager для вычисления метрик
     * @param modules        выбранные модули
     * @param callFromPopup  истина если вызов произошел из контекстного меню проекта
     * @param project        текущий проект
     */
    public ResultViewForm(final String s, final MetricsManager metricsManager, List<Module> modules, boolean callFromPopup,
                          final Project project) {
        super(s);
        $$$setupUI$$$();
        this.metricsManager = metricsManager;
        allModules = metricsManager.getAllModules();
        selectedModules = !callFromPopup ? allModules : modules;
        log.debug("модули проекта для инициализации moduleTableComboBox  :  " + allModules.toString());
        //Заполнение moduleTableComboBox
        versions = new ArrayList<Long>();
        //инициализация списка версий
        setSelectedModules(selectedModules);
        versions = new ArrayList<Long>();
        setVersions(selectedModules);
        log.debug("moduleTableComboBox инициализирован  ");
        //обработка нажатия на кнопку "Добавить/Удалить модуль"
        //показывает соответствующую форму
        addModuleButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                log.info("Нажата кнопка \"Добавить/удалить форму\"");
                viewAddModuleForm();
            }
        });
        //обработка нажатия на кнопку "Применить"
        applyButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                log.info("Нажата кнопка \"Применить\"");
                CalculateMetricsProgressTask task = new CalculateMetricsProgressTask(project, ResultViewForm.this, metricsManager);
                task.queue();
            }
        });
        //обработка нажатия на кнопку "Выгрузить" для таблицы
        exportTablButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                log.info("Нажата кнопка \"Выгрузить\" для таблицы");
                exportMertics();
            }
        });
        //обработка нажатия на кнопку "Построить график" для секторного графика
        buildGraphic2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                log.info("Нажата кнопка \"Построить график\" для секторного графика");
                buildPieChartGraphic(metricsManager);
            }
        });
        //обработка нажатия на кнопку "Выгрузить" для секторного графика
        unloadGraphicButton2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                log.info("Нажата кнопка \"Выгрузить\" для секторного графика");
                unloadPieChartGraphic();
            }
        });
        //обработка нажатия на кнопку "Построить график" для графика-гистрограммы
        buildGraphic1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                log.info("Нажата кнопка \"Построить график\" для гистограммы");
                buildBarChartGraphic(metricsManager);
            }
        });
        //обработка нажатия на кнопку "Выгрузить" для графика - гистрограммы
        unloadGraphicButton1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                log.info("Нажата кнопка \"Выгрузить\" для гистограммы");
                unloadBarChartGraphic();
            }
        });
        //обработка действия с первым combobox
        //заполнение versions выбранными ревизиями
        ActionListener revisionsBoxListener = new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                fillVersions();
            }
        };
        firstRevisionComboBox.addActionListener(revisionsBoxListener);
        //обработка действия со вторым combobox
        //заполнение versions выбранными ревизиями
        lastRevisionComboBox.addActionListener(revisionsBoxListener);
        //добавление слушателя состояния базы данных.
        BaloonNotificationDatabaseListener listener = new BaloonNotificationDatabaseListener(project, this);
        this.metricsManager.getDataBaseManager().addStateListener(listener);

    }

    public void showBottomMessage(final String message, final String text) {
        bottomLabel.setVisible(true);
        bottomLabel.setText(text);
        bottomLabel.setToolTipText(message);
    }

    public void hideBottomMessage() {
        bottomLabel.setVisible(false);
    }

    public void updateVersions() {
        setVersions(resultModules);
    }

    /**
     * заполняет versions выбранными пользовтелем ревизиями
     */

    private void fillVersions() {
        boolean isNotEmpty = (firstRevisionComboBox.getItemCount() != 0 && lastRevisionComboBox.getItemCount() != 0);
        if(isNotEmpty) {
            int firstIndex = firstRevisionComboBox.getSelectedIndex();
            int lastIndex = lastRevisionComboBox.getSelectedIndex();
            Long firstVersion;
            if(firstRevisionComboBox.getSelectedItem() == "MODIFIED") {
                firstVersion = MetricsManager.MODIFIED;
            } else if(firstRevisionComboBox.getSelectedItem() == "LOCAL") {
                firstVersion = MetricsManager.LOCAL;
            } else {
                firstVersion = (Long)firstRevisionComboBox.getSelectedItem();
            }
            Long lastVersion;
            if(lastRevisionComboBox.getSelectedItem() == "MODIFIED") {
                lastVersion = MetricsManager.MODIFIED;
            } else if(lastRevisionComboBox.getSelectedItem() == "LOCAL") {
                lastVersion = MetricsManager.LOCAL;
            } else {
                lastVersion = (Long)lastRevisionComboBox.getSelectedItem();
            }
            versions.clear();
            versions.add(firstVersion);
            if(!firstVersion.equals(lastVersion)) {
                for (int i = firstIndex + 1; i < lastIndex; i++) {
                    versions.add(allVersions.get(i));
                }
                versions.add(lastVersion);
            }
        }
    }

    /**
     * открывает диалог выбора файла и экспортирует в выбранный файл график - гистограмму
     */
    private void unloadBarChartGraphic() {
        try {
            File file = chooseFile(graphicFileFilter);
            if(file != null) {
                FileOutputStream outputStream = new FileOutputStream(file);
                log.info("создан поток для записи");
                Exporter.exportGraphic(outputStream, chartBar.getChart(), metricGraphic1.getWidth(), metricGraphic1.getHeight());
            }
        } catch (IOException e) {
            log.error("ошибка при выгрузке графика в файл", e);
        }
    }

    /**
     * строит гистограмму по выбранной метрике и добавленным модулям
     *
     * @param metricsManager объект MetricsManager для вычисления метрик
     */
    private void buildBarChartGraphic(MetricsManager metricsManager) {
        if(selectedModules.size() != 0) {
            int selectedIndex = metricsGraphicComboBox1.getSelectedIndex();
            resultModules = new ArrayList<Module>(selectedModules);
            List<MetricCalculator> metricCalculators = new ArrayList<MetricCalculator>();
            // определение выбранной метрики в зависимости от индекса
            // выбранного элемента в комбобоксе с метриками
            // (0..4), где 0 - верхний, 4 - нижний
            switch (selectedIndex) {
                case 0:
                    metricCalculators.add(new ClassCountMetricCalculator());
                    break;
                case 1:
                    metricCalculators.add(new AbstractClassCountMetricCalculator());
                    break;
                case 2:
                    metricCalculators.add(new InterfaceCountMetricCalculator());
                    break;
                case 3:
                    metricCalculators.add(new LinesOfCodeMetricCalculator());
                    break;
                case 4:
                    metricCalculators.add(new SourceInstructionsMetricCalculator());
                    break;
            }
            log.debug("Выбранная метрика " + metricCalculators.get(0).toString());
            Map<String, Long> modulesAndMetrics = new HashMap<String, Long>();
            ArrayList<Long> currentVersions = new ArrayList<Long>();
            for (Module module : selectedModules) {
                currentVersions.clear();
                Long current = MetricsManager.currentVersion(module);
                currentVersions.add(current);
                Map<Long, List<Long>> values = metricsManager
                        .calculateMetricsByModule(metricsManager.getProject(), module, currentVersions, metricCalculators);
                List<Long> calculatedMetrics = (values.values()).iterator().next();
                //здесь берется последняя метрика так как строится график для всех модулей ПО ОДНОЙ метрике
                modulesAndMetrics.put(module.getName(), calculatedMetrics.get(0));
            }
            chartBar.setGraphicName("График для метрики " + metricCalculators.get(0).toString());
            chartBar.createGraphic(modulesAndMetrics);
        } else {
            Messages.showMessageDialog("Не выбрано ни одного модуля", "ошибка", null);
        }
    }

    /**
     * открывает диалог выбора файла и экспортирует в выбранный файл секторный график
     */
    private void unloadPieChartGraphic() {
        try {
            File file = chooseFile(graphicFileFilter);
            if(file != null) {
                FileOutputStream outputStream = new FileOutputStream(file);
                log.info("создан поток для записи");
                Exporter.exportGraphic(outputStream, pieChart.getChart(), metricGraphic2.getWidth(), metricGraphic2.getHeight());
            }
        } catch (IOException e) {
            log.error("ошибка при выгрузке графика в файл", e);
        }
    }

    /**
     * строит секторный график для выбранных метрик и модуля
     *
     * @param metricsManager объект MetricsManager для вычисления метрик
     */
    private void buildPieChartGraphic(MetricsManager metricsManager) {
        if(selectedModules.size() != 0) {
            int selectedIndex = metricsGraphicComboBox2.getSelectedIndex();
            int selectedModule = moduleGraphicComboBox2.getSelectedIndex();
            List<MetricCalculator> metricCalculators = new ArrayList<MetricCalculator>();
            if(selectedIndex == 0) {
                metricCalculators.add(new LinesOfCodeMetricCalculator());
                metricCalculators.add(new SourceInstructionsMetricCalculator());
            } else {
                metricCalculators.add(new ClassCountMetricCalculator());
                metricCalculators.add(new AbstractClassCountMetricCalculator());
                metricCalculators.add(new InterfaceCountMetricCalculator());
            }
            Module currentModule = selectedModules.get(selectedModule);
            ArrayList<Long> currentVersion = new ArrayList<Long>();
            currentVersion.add(MetricsManager.currentVersion(currentModule));
            Map<Long, List<Long>> calculatedMetrics = metricsManager
                    .calculateMetricsByModule(metricsManager.getProject(), currentModule, versions, metricCalculators);
            Map<String, Long> metricsInfo = new HashMap<String, Long>();
            //берется последняя (текущая) версия
            List<Long> metricsValues = calculatedMetrics.get(currentVersion.get(0));
            if(metricsValues == null) {
                metricsValues = (calculatedMetrics.values()).iterator().next();
            }
            for (int i = 0; i < metricCalculators.size(); i++) {
                log.debug(metricCalculators.get(i).toString() + " : " + metricsValues.get(i));
                metricsInfo.put(metricCalculators.get(i).toString(), metricsValues.get(i));
            }
            pieChart.setGraphicName("График для модуля " + selectedModules.get(selectedModule).getName());
            pieChart.createGraphic(metricsInfo);
        } else {
            Messages.showMessageDialog("Не выбрано ни одного модуля", "ошибка", null);
        }
    }

    /**
     * экспортирует таблицу метрик в выбранный пользователем файл
     */
    private void exportMertics() {
        if(metricsValues.size() != 0) {
            List<String> listNameMetric = new ArrayList<String>();
            for (MetricCalculator metricCalculator : metricCalculators) {
                listNameMetric.add(metricCalculator.toString());
            }
            log.debug("список имен метрик : " + listNameMetric);
            log.debug("данные для выгрузки таблицы в файл " + metricsValues);
            csvExport(listNameMetric);
        } else {
            Messages.showMessageDialog("нет таблицы для выгрузки", "ошибка", null);
        }
    }

    /**
     * открывает диалог выбора файла и экспортирует метрики с именами из списка listNameMetric в файл
     *
     * @param listNameMetric список имен метрик для экспорта
     */
    private void csvExport(List<String> listNameMetric) {
        try {
            File file = chooseFile(tableFileFilter);
            if(file != null) {
                FileOutputStream outputStream = new FileOutputStream(file);
                log.info("создан поток для записи");
                Exporter.exportTable(metricsValues, listNameMetric, outputStream);
            }
        } catch (IOException e) {
            log.error("ошибка при выгрузке таблицы в файл", e);
        }
    }

    /**
     * выполняет перерасчет данных для таблицы метрик
     *
     * @param metricsManager объект MetricsManager для вычисления метрик
     */
    public void calcMetricsTable(MetricsManager metricsManager) {
        if(selectedModules.size() > 0) {
            metricCalculators = getSelectedMetric();
            if(metricCalculators.size() > 0) {
                log.debug("Выбранные метрики: " + metricCalculators.toString());
                resultModules = getSelectedModules();
                //вычисление значений метрик
                //Копирование versions нужно для того, чтобы избежать ConcurrentModificationException.
                //При возникновении ошибки с базой сообщение об этом заставляет перерисоваться список версий
                //в combobox'ах и при этом происходит модификация versions
                metricsValues = metricsManager
                        .сalculateMetrics(metricsManager.getProject(), resultModules, new ArrayList<Long>(versions), metricCalculators);
                log.info("значения метрик: " + metricsValues.toString());
                viewMetricsValue();
            } else {
                Messages.showMessageDialog("Не выбрано ни одной метрики", "ошибка", null);
            }
        } else {
            Messages.showMessageDialog("Не выбрано ни одного модуля", "ошибка", null);
        }
    }

    /**
     * определяет выбранные из moduleTableComboBox пользователем модули (все либо один)
     *
     * @return список выбранных модулей
     */
    private ArrayList<Module> getSelectedModules() {
        int selectedIndex = moduleTableComboBox.getSelectedIndex();
        log.debug("индекс выбранного модуля = " + selectedIndex);
        if(selectedIndex == 0) {
            return new ArrayList<Module>(selectedModules);
        } else {
            Module selectedModule = allModules.get(0);
            boolean isModuleSelected = allModules.get(0).getName().equalsIgnoreCase(moduleTableComboBox.getSelectedItem().toString());
            int i = 1;
            while (!isModuleSelected & (i < allModules.size())) {
                isModuleSelected = allModules.get(i).getName().equalsIgnoreCase(moduleTableComboBox.getSelectedItem().toString());
                i++;
            }
            if(isModuleSelected) {
                selectedModule = allModules.get(i - 1);
            }
            return new ArrayList<Module>(Arrays.asList(selectedModule));
        }
    }

    /**
     * Отображает полученные значения метрик в таблицу
     */
    private void viewMetricsValue() {
        final List<Object> headers = new ArrayList<Object>(Arrays.asList("Ревизия"));
        List<String> headersUp = new ArrayList<String>();
        //создание заголовка таблицы
        initRevisionTableHeaders(headers, headersUp);
        int columnCount = resultModules.size() * metricCalculators.size() + 1;
        int rowCount = versions.size();
        //отображение полученных значений в таблице
        //определяем, есть ли среди посчитанных версий информация по текущей версии
        String[][] dataVector = new String[rowCount][columnCount];
        int columnIndex = 1;
        for (String moduleName : headersUp) {
            log.info("копируем метрики для модуля : " + moduleName);
            Map<Long, List<Long>> verAndMetrics = metricsValues.get(moduleName);
            //получаем множество всех версий текущего модуля
            for (Long version : versions) {
                if(verAndMetrics.containsKey(version)) {
                    int rowIndex = versions.indexOf(version);
                    int j = columnIndex;
                    List<Long> writtedMertics = verAndMetrics.get(version);
                    for (Long metric : writtedMertics) {
                        //значение метрики может быть null, если по текущей версии посчитаны не все метрики, 
                        //потом исходник модуля модифицирован и поступил запрос на подсчет всех метрик
                        if(metric != null) {
                            dataVector[rowIndex][j] = metric.toString();
                        }
                        j++;
                    }
                }
            }
            columnIndex = columnIndex + metricCalculators.size();
        }
        for (int i = 0; i < rowCount; i++) {
            long version = versions.get(i);
            if(version == MetricsManager.MODIFIED) {
                dataVector[i][0] = "MODIFIED";
            } else if(version == MetricsManager.LOCAL) {
                dataVector[i][0] = "LOCAL";
            } else {
                dataVector[i][0] = String.valueOf(versions.get(i));
            }
        }
        revisionTable.setModel(new DefaultTableModel(dataVector, headers.toArray()));
        int metricsCount = metricCalculators.size();
        TableColumnModel tableColumnModel = revisionTable.getColumnModel();
        ColumnGroup[] columnGroups = new ColumnGroup[headersUp.size()];
        int j = 1;
        for (int i = 0; i < headersUp.size(); i++) {
            columnGroups[i] = new ColumnGroup((headersUp.get(i)));
            for (int t = j; t < j + metricsCount; t++) {
                columnGroups[i].add(tableColumnModel.getColumn(t));
            }
            j = j + metricsCount;
        }
        GroupableTableHeader header = (GroupableTableHeader)revisionTable.getTableHeader();
        for (int i = 0; i < headersUp.size(); i++) {
            header.addColumnGroup(columnGroups[i]);
        }
    }

    /**
     * инициализирует заголовки таблицы в зависимости от выбранных модулей и метрик
     *
     * @param headers   список, хранящий заголовки столбцов
     * @param headersUp список, хранящий заголовки групп столбцов
     */
    private void initRevisionTableHeaders(List<Object> headers, List<String> headersUp) {
        for (Module module : resultModules) {
            headersUp.add(module.getName());
        }
        int groupColumnsCount = resultModules.size();
        for (int i = 0; i < groupColumnsCount; i++) {
            headers.addAll(metricCalculators);
        }
        log.info("заголовок таблицы headers: " + headers);
        log.info("заголовок таблицы headersUp: " + headersUp);
    }

    /**
     * создает форму AddModuleForm если она еще не была создана и показывает ее
     */
    private void viewAddModuleForm() {
        if(addModuleForm != null) {
            addModuleForm.setVisible(true);
            log.debug("показана форма AddModuleForm");
        } else {
            log.debug(selectedModules + "");
            log.debug("all   " + allModules);
            addModuleForm = new JFrame();
            AddModuleForm form = new AddModuleForm(allModules, selectedModules, this, addModuleForm);
            addModuleForm.getContentPane().add(form.getRootPanel());
            addModuleForm.setVisible(true);
            addModuleForm.pack();
            log.debug("создана форма AddModuleForm");
        }
    }

    /**
     * @return список метрик, выбранных пользователем на форме ResultViewForm
     */
    private List<MetricCalculator> getSelectedMetric() {
        List<MetricCalculator> metricCalculators = new ArrayList<MetricCalculator>();
        Map<JCheckBox, MetricCalculator> map = new LinkedHashMap<JCheckBox, MetricCalculator>() {
            {
                put(classCheckBox, new ClassCountMetricCalculator());
                put(abstractClassCheckBox, new AbstractClassCountMetricCalculator());
                put(interfaceCheckBox, new InterfaceCountMetricCalculator());
                put(codeLineCheckBox, new LinesOfCodeMetricCalculator());
                put(codeLineRealCheckBox, new SourceInstructionsMetricCalculator());
            }
        };
        for (JCheckBox checkbox : map.keySet()) {
            if(checkbox.isSelected()) {
                metricCalculators.add(map.get(checkbox));
            }
        }
        return metricCalculators;

    }

    /**
     * записывает модули в combobox с модулями
     *
     * @param modules список модулей, которые вносятся в combobox
     */
    public void setSelectedModules(List<Module> modules) {
        selectedModules = new ArrayList<Module>(modules);
        moduleTableComboBox.removeAllItems();
        moduleGraphicComboBox2.removeAllItems();
        if(modules.size() > 0) {
            moduleTableComboBox.addItem("Все в ряд");
            for (Module module : selectedModules) {
                moduleTableComboBox.addItem(module.getName());
                moduleGraphicComboBox2.addItem(module.getName());
            }
        }
    }

    /**
     * заполняет версиями firstRevisionComboBox и lastRevisionComboBox
     *
     * @param modules список модулей, для которых заполняются версии (ревизии)
     */
    public void setVersions(List<Module> modules) {
        if(allVersions == null) {
            allVersions = new ArrayList<Long>();
        } else {
            allVersions.clear();
        }

        allVersions = metricsManager.getAllVersion(metricsManager.getProject().getName(), modules);
        firstRevisionComboBox.setEnabled(true);
        lastRevisionComboBox.setEnabled(true);
        moduleTableComboBox.setEnabled(true);
        moduleGraphicComboBox2.setEnabled(true);
        firstRevisionComboBox.removeAllItems();
        lastRevisionComboBox.removeAllItems();
        for (Long version : allVersions) {
            if(version == MetricsManager.MODIFIED) {
                firstRevisionComboBox.addItem("MODIFIED");
                lastRevisionComboBox.addItem("MODIFIED");
            } else if(version == MetricsManager.LOCAL) {
                firstRevisionComboBox.addItem("LOCAL");
                lastRevisionComboBox.addItem("LOCAL");
            } else {
                firstRevisionComboBox.addItem(version);
                lastRevisionComboBox.addItem(version);
            }
        }
        if(lastRevisionComboBox.getItemCount() != 0) {
            lastRevisionComboBox.setSelectedIndex(lastRevisionComboBox.getItemCount() - 1);
        } else {
            firstRevisionComboBox.setEnabled(false);
            lastRevisionComboBox.setEnabled(false);
            moduleTableComboBox.setEnabled(false);
            moduleGraphicComboBox2.setEnabled(false);
        }
        versions = new ArrayList<Long>(allVersions);
    }

    /**
     * Создает диалоговое окно для выбора пути, по которому будет сохранен файл
     *
     * @param filter задает тип фильтрации выбора файлов
     *
     * @return возвращает выбранный файл или null, если файл не выбран
     * @throws IOException при неудачном создании диалога выдается исключение ввода/вывода
     */
    public static File chooseFile(FileNameExtensionFilter filter) throws IOException {
        JFileChooser fileChooser = new JFileChooser();
        //создаем фильтр выбора файлов и добавляем его в диалог
        fileChooser.addChoosableFileFilter(filter);
        int chooseResult = fileChooser.showDialog(null, "Save file");
        if(chooseResult == JFileChooser.APPROVE_OPTION) {
            File file = fileChooser.getSelectedFile();
            if(!filter.accept(file)) {
                String fileName = file.getAbsolutePath() + "." + filter.getExtensions()[0];
                file = new File(fileName);
            }
            return file;
        }
        return null;
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     */

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     */

    private void createUIComponents() {

        revisionTable = new JTable() {
            protected JTableHeader createDefaultTableHeader() {
                return new GroupableTableHeader(columnModel);
            }
        };
        revisionTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        chartBar = new BarChartGraphic();
        pieChart = new PieChartGraphic();
        metricGraphic1 = chartBar.createGraphicSpace();
        metricGraphic2 = pieChart.createGraphicSpace();
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     */
    private void $$$setupUI$$$() {
        createUIComponents();
        rootPanel = new JPanel();
        rootPanel.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1));
        final JPanel panel1 = new JPanel();
        panel1.setLayout(new GridLayoutManager(1, 4, new Insets(0, 0, 0, 0), -1, -1));
        panel1.setToolTipText("");
        rootPanel.add(panel1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        panel1.setBorder(BorderFactory.createTitledBorder("Отобразить ревизии"));
        final JLabel label1 = new JLabel();
        label1.setText("с");
        panel1.add(label1,
                new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED,
                        GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        firstRevisionComboBox = new JComboBox();
        firstRevisionComboBox.setEnabled(true);
        panel1.add(firstRevisionComboBox, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        final JLabel label2 = new JLabel();
        label2.setText("по");
        panel1.add(label2,
                new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED,
                        GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        lastRevisionComboBox = new JComboBox();
        lastRevisionComboBox.setEnabled(true);
        panel1.add(lastRevisionComboBox, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        final JPanel panel2 = new JPanel();
        panel2.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1));
        rootPanel.add(panel2, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        final JPanel panel3 = new JPanel();
        panel3.setLayout(new GridLayoutManager(1, 2, new Insets(0, 0, 0, 0), -1, -1));
        panel2.add(panel3, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        addModuleButton = new JButton();
        addModuleButton.setEnabled(true);
        addModuleButton.setText("Добавить/Удалить модули");
        addModuleButton.setMnemonic('Д');
        addModuleButton.setDisplayedMnemonicIndex(0);
        addModuleButton.setVisible(true);
        panel3.add(addModuleButton, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null,
                null, 0, false));
        final Spacer spacer1 = new Spacer();
        panel3.add(spacer1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false));
        resultViewTabbedPane1 = new JTabbedPane();
        resultViewTabbedPane1.setEnabled(true);
        panel2.add(resultViewTabbedPane1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, new Dimension(700, 500), null, 0,
                false));
        final JPanel panel4 = new JPanel();
        panel4.setLayout(new GridLayoutManager(3, 1, new Insets(0, 0, 0, 0), -1, -1));
        resultViewTabbedPane1.addTab("Таблица", panel4);
        final JPanel panel5 = new JPanel();
        panel5.setLayout(new GridLayoutManager(1, 2, new Insets(0, 0, 0, 0), -1, -1));
        panel4.add(panel5, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        final JLabel label3 = new JLabel();
        label3.setText("Показать метрики для ");
        panel5.add(label3,
                new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED,
                        GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        moduleTableComboBox = new JComboBox();
        final DefaultComboBoxModel defaultComboBoxModel1 = new DefaultComboBoxModel();
        defaultComboBoxModel1.addElement("Все в ряд");
        moduleTableComboBox.setModel(defaultComboBoxModel1);
        panel5.add(moduleTableComboBox, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        final JPanel panel6 = new JPanel();
        panel6.setLayout(new GridLayoutManager(3, 2, new Insets(0, 0, 0, 0), -1, -1));
        panel4.add(panel6, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        panel6.setBorder(BorderFactory.createTitledBorder("Отбразить метрики"));
        classCheckBox = new JCheckBox();
        classCheckBox.setSelected(true);
        classCheckBox.setText("Количество классов (СС)");
        panel6.add(classCheckBox, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null,
                null, 0, false));
        abstractClassCheckBox = new JCheckBox();
        abstractClassCheckBox.setSelected(true);
        abstractClassCheckBox.setText("Количество абстрактных классов (AC)");
        panel6.add(abstractClassCheckBox, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null,
                null, 0, false));
        interfaceCheckBox = new JCheckBox();
        interfaceCheckBox.setSelected(true);
        interfaceCheckBox.setText("Количество интерфейсов (I)");
        panel6.add(interfaceCheckBox, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null,
                null, 0, false));
        codeLineCheckBox = new JCheckBox();
        codeLineCheckBox.setEnabled(true);
        codeLineCheckBox.setHideActionText(false);
        codeLineCheckBox.setSelected(true);
        codeLineCheckBox.setText("Количество строк кода (LOC)");
        codeLineCheckBox.setVisible(true);
        panel6.add(codeLineCheckBox, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null,
                null, 0, false));
        codeLineRealCheckBox = new JCheckBox();
        codeLineRealCheckBox.setEnabled(true);
        codeLineRealCheckBox.setSelected(true);
        codeLineRealCheckBox.setText("Количество строк кода без комментариев и пустых строк (LWC)");
        panel6.add(codeLineRealCheckBox, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null,
                null, 0, false));
        final JPanel panel7 = new JPanel();
        panel7.setLayout(new GridLayoutManager(1, 3, new Insets(0, 0, 0, 0), -1, -1));
        panel6.add(panel7, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        exportTablButton = new JButton();
        exportTablButton.setText("Выгрузить");
        panel7.add(exportTablButton, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED,
                new Dimension(70, -1), null, null, 0, false));
        applyButton = new JButton();
        applyButton.setText("Применить");
        applyButton.setMnemonic('П');
        applyButton.setDisplayedMnemonicIndex(0);
        panel7.add(applyButton, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null,
                null, 0, false));
        final Spacer spacer2 = new Spacer();
        panel7.add(spacer2, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false));
        final JScrollPane scrollPane1 = new JScrollPane();
        scrollPane1.setToolTipText("");
        panel4.add(scrollPane1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
        scrollPane1.setViewportView(revisionTable);
        final JPanel panel8 = new JPanel();
        panel8.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
        resultViewTabbedPane1.addTab("График 1", panel8);
        final JPanel panel9 = new JPanel();
        panel9.setLayout(new GridLayoutManager(3, 1, new Insets(0, 0, 0, 0), -1, -1));
        panel8.add(panel9, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        panel9.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION,
                TitledBorder.DEFAULT_POSITION,
                new Font(panel9.getFont().getName(), panel9.getFont().getStyle(), panel9.getFont().getSize())));
        final JPanel panel10 = new JPanel();
        panel10.setLayout(new GridLayoutManager(1, 2, new Insets(0, 0, 0, 0), -1, -1));
        panel9.add(panel10, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        final JLabel label4 = new JLabel();
        label4.setText("по метрике ");
        panel10.add(label4,
                new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED,
                        GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        metricsGraphicComboBox1 = new JComboBox();
        final DefaultComboBoxModel defaultComboBoxModel2 = new DefaultComboBoxModel();
        defaultComboBoxModel2.addElement("CC");
        defaultComboBoxModel2.addElement("CA");
        defaultComboBoxModel2.addElement("I");
        defaultComboBoxModel2.addElement("LOC");
        defaultComboBoxModel2.addElement("LOC No Comment And Empty");
        metricsGraphicComboBox1.setModel(defaultComboBoxModel2);
        panel10.add(metricsGraphicComboBox1, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        final JPanel panel11 = new JPanel();
        panel11.setLayout(new GridLayoutManager(1, 3, new Insets(0, 0, 0, 0), -1, -1));
        panel9.add(panel11, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        unloadGraphicButton1 = new JButton();
        unloadGraphicButton1.setText("Выгрузить");
        unloadGraphicButton1.setMnemonic('В');
        unloadGraphicButton1.setDisplayedMnemonicIndex(0);
        panel11.add(unloadGraphicButton1, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null,
                new Dimension(103, 25), null, 0, false));
        buildGraphic1 = new JButton();
        buildGraphic1.setText("Построить график");
        panel11.add(buildGraphic1, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null,
                null, 0, false));
        final Spacer spacer3 = new Spacer();
        panel11.add(spacer3, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false));
        panel9.add(metricGraphic1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, new Dimension(24, 227), null, 0, false));
        final JPanel panel12 = new JPanel();
        panel12.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
        panel12.setVerifyInputWhenFocusTarget(false);
        panel12.setVisible(true);
        resultViewTabbedPane1.addTab("График 2", panel12);
        final JPanel panel13 = new JPanel();
        panel13.setLayout(new GridLayoutManager(3, 1, new Insets(0, 0, 0, 0), -1, -1));
        panel12.add(panel13, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        panel13.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLoweredBevelBorder(), null));
        final JPanel panel14 = new JPanel();
        panel14.setLayout(new GridLayoutManager(2, 2, new Insets(0, 0, 0, 0), -1, -1));
        panel13.add(panel14, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        final JLabel label5 = new JLabel();
        label5.setText("Отобразить метрики");
        panel14.add(label5,
                new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED,
                        GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        final JLabel label6 = new JLabel();
        label6.setText("для модуля ");
        panel14.add(label6,
                new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED,
                        GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        metricsGraphicComboBox2 = new JComboBox();
        final DefaultComboBoxModel defaultComboBoxModel3 = new DefaultComboBoxModel();
        defaultComboBoxModel3.addElement("LOC/LOC no Comment  And Empty");
        defaultComboBoxModel3.addElement("CC/CA/I");
        metricsGraphicComboBox2.setModel(defaultComboBoxModel3);
        panel14.add(metricsGraphicComboBox2, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        moduleGraphicComboBox2 = new JComboBox();
        panel14.add(moduleGraphicComboBox2, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        final JPanel panel15 = new JPanel();
        panel15.setLayout(new GridLayoutManager(1, 3, new Insets(0, 0, 0, 0), -1, -1));
        panel13.add(panel15, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        unloadGraphicButton2 = new JButton();
        unloadGraphicButton2.setText("Выгрузить");
        unloadGraphicButton2.setMnemonic('В');
        unloadGraphicButton2.setDisplayedMnemonicIndex(0);
        panel15.add(unloadGraphicButton2, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null,
                null, 0, false));
        buildGraphic2 = new JButton();
        buildGraphic2.setText("Построить график");
        panel15.add(buildGraphic2, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null,
                null, 0, false));
        final Spacer spacer4 = new Spacer();
        panel15.add(spacer4, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false));
        panel13.add(metricGraphic2, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, new Dimension(24, 260), null, 0, false));
        label1.setLabelFor(firstRevisionComboBox);
        label2.setLabelFor(lastRevisionComboBox);
        label3.setLabelFor(moduleTableComboBox);
        label4.setLabelFor(metricsGraphicComboBox1);
    }

    /**
     * @noinspection ALL
     */
    public JComponent $$$getRootComponent$$$() {
        return rootPanel;
    }
}
